package factories;

import com.jme.scene.Node;

import fileHandling.ModelImporter;
import fileHandling.SettingsLoader;
import fileHandling.language.properties.WeaponProps;
import logic.common.team.Fraction;
import logic.nodes.nodeSettings.upgrades.UpgradableSettings;
import logic.ships.Ship;
import logic.ships.hunter.Hunter;
import logic.weapons.Weapon;
import logic.weapons.WeaponProperties;
import logic.weapons.energyWeapons.EnergyWeapon;
import logic.weapons.projectileWeapons.ProjectileWeapon;
import logic.weapons.projectileWeapons.ProjectileProperties;
import logic.weapons.projectileWeapons.artillary.ArtillaryWeapon;
import logic.weapons.projectileWeapons.artillary.ArtillaryProperties;
import logic.weapons.projectileWeapons.heatSeeker.HeatSeekerProperties;
import logic.weapons.projectileWeapons.heatSeeker.HeatSeekerWeapon;
import logic.weapons.projectileWeapons.missile.MissileWeapon;
import logic.weapons.projectileWeapons.missile.MissileProperties;

/**
 * Provides methods to create new {@link Weapons}.
 * 
 * @author Wasserleiche
 */
public class WeaponFactory {
	
	/**
	 * Creates a new {@link Weapon} with the given information. If the resulting {@link WeaponProperties} 
	 * are {@link ProjectileProperties}, a {@link ProjectileWeapon} will be created, else a 
	 * {@link EnergyWeapon} will be created.
	 * @param fraction The {@link Fraction} the {@link Weapon} belongs to.
	 * @param weaponName The name of the {@link Weapon}.
	 * @param weaponCarrier The {@link WeaponCarrier} the {@link Weapon} will belong to.
	 * @return A new instance of {@link Weapon}. null, if an error occurred.
	 */
	public static Weapon createHunterWeapon(Fraction fraction, String weaponName, Hunter ship) {
		String f = fraction.toString().toLowerCase();
		String weaponPath = "data/fractions/" + f + "/hunterWeapons/" + weaponName + "/";
		return createNewWeapon(weaponName, weaponPath, ship);
	}
	
	public static Weapon createNewWeapon(String weaponName, String weaponPath, Ship ship) {
		WeaponProperties props = getWeaponProperties(weaponPath);
		if(props == null) return null;
		
		String modelPath = props.getModelPath();
		Node weaponModel = ModelImporter.getModel(modelPath);
		if(weaponModel == null) return null;
		
		return createNewWeapon(weaponName, ship, props);
	}
	
	public static Weapon createNewWeapon(String weaponName, Ship ship, WeaponProperties props) {
		String modelPath = props.getModelPath();
		Node weaponModel = ModelImporter.getModel(modelPath);
		
		if(props instanceof ArtillaryProperties) 
			return new ArtillaryWeapon(weaponModel, modelPath, weaponName, (ArtillaryProperties)props, ship);
		if(props instanceof HeatSeekerProperties) {
			assert(ship instanceof Hunter);
			return new HeatSeekerWeapon(weaponModel, modelPath, weaponName, (HeatSeekerProperties)props, (Hunter)ship);
		}
		if(props instanceof MissileProperties) 
			return new MissileWeapon(weaponModel, modelPath, weaponName, (MissileProperties)props, ship);
		return new EnergyWeapon(weaponModel, modelPath, weaponName, props, ship);
	}
	
	/**
	 * Returns the {@link WeaponProperties} of the given {@link Weapon}.
	 * @param weaponPath The relative path to the {@link Weapon} (with / at the end).
	 * @return A {@link WeaponProperties}-object. null, if it could not be created.
	 */
	public static WeaponProperties getWeaponProperties(String weaponPath) {
		UpgradableSettings settings = SettingsLoader.loadUpgradableSettings(weaponPath + "properties.xml");
		String type = settings.getValueOf(WeaponProps.WeaponType);
		if(type.equals(WeaponProps.Energy.toString())) return new WeaponProperties(settings);
		else if(type.equals(WeaponProps.Artillary.toString())) return new ArtillaryProperties(settings);
		else if(type.equals(WeaponProps.Heatseeker.toString())) return new HeatSeekerProperties(settings);
		return new MissileProperties(settings);
	}
}